package com.xiaowu.house.user.service.impl;


import com.xiaowu.house.appuser.domain.dto.UserEditReqDTO;
import com.xiaowu.house.appuser.domain.vo.AppUserVo;
import com.xiaowu.house.appuser.feign.AppUserFeignClient;
import com.xiaowu.house.domain.R;
import com.xiaowu.house.domain.ResultCode;
import com.xiaowu.house.domain.dto.LoginUserDTO;
import com.xiaowu.house.domain.dto.TokenDTO;
import com.xiaowu.house.domain.vo.LoginUserVO;
import com.xiaowu.house.exception.ServiceException;
import com.xiaowu.house.service.CaptchaService;
import com.xiaowu.house.service.TokenService;
import com.xiaowu.house.user.entity.dto.CodeLoginDTO;
import com.xiaowu.house.user.entity.dto.LoginDTO;
import com.xiaowu.house.user.entity.dto.UserDTO;
import com.xiaowu.house.user.entity.dto.WechatLoginDTO;
import com.xiaowu.house.user.service.IUserService;
import com.xiaowu.house.utils.JwtUtil;
import com.xiaowu.house.utils.SecurityUtil;
import com.xiaowu.house.utils.VerifyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private AppUserFeignClient appUserFeignClient;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private CaptchaService captchaService;


    @Override
    public TokenDTO login(LoginDTO loginDTO) {
        LoginUserDTO loginUserDTO = new LoginUserDTO();

        if (loginDTO instanceof WechatLoginDTO wechatLoginDTO) {
            //处理微信登录逻辑
            loginByWechat(wechatLoginDTO, loginUserDTO);
        }

        if (loginDTO instanceof CodeLoginDTO codeLoginDTO) {
            loginByCode(codeLoginDTO, loginUserDTO);
        }

        loginUserDTO.setUserFrom("app");
        return tokenService.createToken(loginUserDTO);
    }

    @Override
    public String sendCode(String phone) {
        if (!VerifyUtil.checkPhone(phone)) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "手机号格式错误");
        }
        return captchaService.sendCode(phone);

    }

    @Override
    public void edit(UserEditReqDTO userEditReqDTO) {
        R<Void> result = appUserFeignClient.edit(userEditReqDTO);
        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new ServiceException("修改用户失败");
        }
    }

    @Override
    public UserDTO getLoginUser() {
        LoginUserDTO loginUserDTO = tokenService.getLoginUser();
        if (loginUserDTO == null) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "用户令牌有误");
        }

        R<AppUserVo> result = appUserFeignClient.findById(loginUserDTO.getUserId());
        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "查询用户失败");
        }
        // 3 对象拼装，返回结果
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(loginUserDTO, userDTO);
        BeanUtils.copyProperties(result.getData(), userDTO);
        return userDTO;
    }

    @Override
    public void logout() {
        // 1 解析令牌
        String token = SecurityUtil.getToken();
        if (StringUtils.isEmpty(token)) {
            return;
        }
        String userName = JwtUtil.getUserName(token);
        String userId = JwtUtil.getUserId(token);
        log.info("{}退出了系统, 用户ID{}", userName, userId);
        // 2 删除用户缓存记录
        tokenService.delLoginUser(token);
    }

    private void loginByCode(CodeLoginDTO codeLoginDTO, LoginUserDTO loginUserDTO) {
        if (!VerifyUtil.checkPhone(codeLoginDTO.getPhone())) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "手机号格式错误");
        }

        AppUserVo appUserVo;

        R<AppUserVo> result = appUserFeignClient.findByPhone(codeLoginDTO.getPhone());

        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
            appUserVo = register(codeLoginDTO);
        } else {
            appUserVo = result.getData();
        }

        String cacheCode = captchaService.getCode(codeLoginDTO.getPhone());
        if (cacheCode == null) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "验证码无效");
        }
        if (!cacheCode.equals(codeLoginDTO.getCode())) {
            throw new ServiceException(ResultCode.INVALID_PARA.getCode(), "验证码错误");
        }

        captchaService.deleteCode(codeLoginDTO.getPhone());

        loginUserDTO.setUserId(appUserVo.getUserId());
        loginUserDTO.setUserName(appUserVo.getNickName());
    }

    private void loginByWechat(WechatLoginDTO wechatLoginDTO, LoginUserDTO loginUserDTO) {
        AppUserVo appUserVo;

        R<AppUserVo> result = appUserFeignClient.findByOpenId(wechatLoginDTO.getOpenId());
        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() ||
                result.getData() == null) {
            // 3 没查到，需要进行注册
            appUserVo = register(wechatLoginDTO);
        } else {
            appUserVo = result.getData();
        }
        // 4 设置登录信息
        loginUserDTO.setUserId(appUserVo.getUserId());
        loginUserDTO.setUserName(appUserVo.getNickName());
    }

    private AppUserVo register(LoginDTO loginDTO) {

        R<AppUserVo> result = null;

        if (loginDTO instanceof WechatLoginDTO wechatLoginDTO) {
            result = appUserFeignClient.registerByOpenId(wechatLoginDTO.getOpenId());
            if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() ||
                    result.getData() == null) {
                log.error("用户注册失败! {}", wechatLoginDTO.getOpenId());
            }
        }

        if (loginDTO instanceof CodeLoginDTO codeLoginDTO) {
            result = appUserFeignClient.registerByPhone(codeLoginDTO.getPhone());
            if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() ||
                    result.getData() == null) {
                log.error("用户注册失败! {}", codeLoginDTO.getPhone());
            }
        }
        return result == null ? null : result.getData();

    }
}
